#!/user/bin/env python
# -*- coding: utf-8 -*-
''' 
Author: Sjy
LastEditTime: 2024-12-16 16:24:42
Description: 根据配置数据生成数据库的管理界面 具备增删改过滤功能
1. 数据展示（全部or部分）
2. 数据编辑（增删改）
3. 数据过滤（筛选）
4. 数据的保存
5. 数据的导出和导入
6. 对外接口
    1. 展示数据界面
    2. 根据指定名称展示编辑修改界面
    3. 获取指定数据接口（全部or部分）
    4. 获取所有数据的接口
'''
__all__= []
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
from abc import ABCMeta,abstractmethod

try:
    from .extable import ReportTable
except:
    from extable import ReportTable

global TYPE_CONFIG
TYPE_CONFIG = {
    "space": 10,
    "margin": [0, 0, 0, 0],
}

class _UiBase(QtWidgets.QWidget):
    """负责整理 UI 布局
    """
    def __init__(self, data:dict={}) -> None:
        """初始化
        Args:
            data (dict, optional): 配置数据. Defaults to None.
        Return:
            None
        """
        super(_UiBase, self).__init__()
        self._widget = None # 记录用于实例化的 widget
        self.__data = data  # 缓存数据信息
        self.__init_layout()
    def __init_layout(self) -> None:
        """初始化布局,当前仅处理水平布局
        Args:
            无
        Return:
            None
        """
        styleParams = self.__data.get('styleParams', {})
        curMargin = styleParams.get('margin', TYPE_CONFIG.get("margin"))
        curSpace = styleParams.get('space', TYPE_CONFIG.get("space"))
        layout = QtWidgets.QHBoxLayout()
        if curMargin != None:
            layout.setContentsMargins(*curMargin)
        if curSpace != None:
            layout.setSpacing(curSpace)
        # 调用接口函数（需要子类实例化的）用于处理展示每行的信息
        self._init_layout_widgets(layout)
        self.setLayout(layout)
    # 接口函数
    @abstractmethod 
    def _init_layout_widgets(self, layout:QtWidgets.QHBoxLayout=None) -> None:
        """初始化当前布局下的 widgets
        Return:
            value (any, optional): 返回的数据. Defaults to "".
        """
        pass
    @abstractmethod 
    def _get(self) -> any:
        """获取数据
        Return:
            value (any, optional): 返回的数据. Defaults to "".
        """
        pass
    @abstractmethod 
    def _set(self, value:any=None) -> None:
        """设置数据
        Args:
            value (str, optional): 传入的数据. Defaults to "".
        """
    def _get_params(self) -> None:
        """获取参数
        Args:
            无
        Return:
            None
        """
        return self.__data
    def _init_label_style(self, label:QtWidgets.QLabel=None) -> None: 
        """初始化标题的样式，这里可以统一设置
        Args:
            label (QtWidgets.QLabel, optional): 左侧标题. Defaults to None.
        Return:
            None
        """
        if not label:return 
        styleParams = self.__data.get('styleParams', {})
        labWidth = styleParams.get('labWidth', TYPE_CONFIG.get("labWidth"))
        if labWidth:
            label.setFixedWidth(labWidth)
    def _init_widget_style(self, widget:QtWidgets.QWidget=None) -> None: 
        """_summary_
        Args:
            label (QtWidgets.QLabel, optional): _description_. Defaults to None.
        """
        if not widget:return 
        styleParams = self.__data.get('styleParams', {})
        minWidth = styleParams.get('minWidth', TYPE_CONFIG.get("minWidth"))
        if minWidth:
            widget.setMinimumWidth(minWidth)
        maxWidth = styleParams.get('maxWidth', TYPE_CONFIG.get("maxWidth"))
        if maxWidth:
            widget.setMaximumWidth(maxWidth)
        widget.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
    def _init_layout_label(self, layout:QtWidgets.QHBoxLayout=None) -> None:
        """初始化标题
        Args:
            无
        Return:
            None
        """
        data = self._get_params()
        typeParams = data.get('typeParams', {})
        title = typeParams.get('title', "")
        lable = QtWidgets.QLabel(title)
        self._init_label_style(lable)
        layout.addWidget(lable)


# 外部使用组件
class UiCustomDbPage(QtWidgets.QWidget):
    
    def __init__(self, data:dict={}, *args,  **kwargs) -> None:
        """初始化
        Args:
            data (dict, optional): 生成界面ui的数据. Defaults to {}.
        Return:
            None
        """
        self.__data = data
        self.__parent = None
        self.__uis = {} # 保存所有的widget 根据objectName 确定 映射ui关系 {key:ui}

    def _setup_ui(self, parent:QtWidgets.QDialog=None) -> None:
        """为主界面设置ui
        Args:
            parent (QtWidgets.QDialog, optional):主界面的对象. Defaults to {}.
        Return:
            None
        """
        self.__parent = parent
        self.__init_window_config()
        qLayout = self.__get_window_layout()
        self.__parent.setLayout(qLayout)
    def _gets(self) -> dict:
        """获取所有的数据, 注意返回的数据中的data 属性对应的是所有的数据，delKeys 是删除的key列表
        Args:
            无
        Return:
            dict: 返回所有的数据
        """
        removeEmpty = self.__data.get('removeEmpty', False)
        delKeys = []
        data = {}
        for key, ui in self.__uis.items():
            if hasattr(ui, "_get"):
                value = ui._get()
                if not removeEmpty or (value !="" and value != None):
                    data[key] = value
                else:
                    delKeys.append(key)
        return {
            "data": data,
            "delKeys": delKeys,
        }
    def _sets(self, data:dict={}) -> None:
        """设置所有的数据
        Args:
            data (dict, optional): 需要设置的数据. Defaults to {}.
        Return:
            None
        """
        for key, ui in self.__uis.items():
            if key in data and hasattr(ui, "_set"):
                ui._set(data.get(key))

    def __init_window_config(self) -> None:
        """初始化窗口配置
        Args:
            无
        Return:
            None
        """
        title = self.__data.get('title', '')
        icon = self.__data.get('icon', '')
        objectName = self.__data.get('objectName', '')
        size = self.__data.get('size', [400, 200])

        if title:
            self.__parent.setWindowTitle(title)
        if icon:
            self.__parent.setWindowIcon(QtGui.QIcon(icon))
        if objectName:
            self.__parent.setObjectName(objectName)
        if size:
            self.__parent.resize(*size)
    def __get_window_layout(self) -> QtWidgets.QWidget:
        """初始化窗口布局也就是主界面的整体布局
        Args:
            无
        Return:
            QtWidgets.QWidget : 返回一个布局对象
        """
        dataLayout = self.__data.get('layout', {})
        margin = dataLayout.get('margin', [10, 10, 10, 10])
        space = dataLayout.get('space', 10)
        objectName = dataLayout.get('objectName', "")
    
        qLayout = QtWidgets.QVBoxLayout()
        qLayout.setContentsMargins(*margin)
        qLayout.setSpacing(space)
        qLayout.setObjectName(objectName)
        return qLayout
    
if __name__ == '__main__':
    # 测试例子
    app = QtWidgets.QApplication(sys.argv)

    dlg = QtWidgets.QDialog()
    uiConfigData = {
        "title": "测试", # window title 
        "icon": "icon.png", # window icon
        "objectName": "test", # window objectName
        "size": [400, 200], # window size
        "layout":{ # window 主布局
            "margin": [10, 10, 10, 10], # window 主布局的margin
            "space": 10,  # window 主布局的 Space
            "objectName": "qLayout", # window 主布局的 objectName
        },
        "headers":[
            {
                "type": "str",
                "typeParams": { 
                    "title": "str",
                    "objectName": "name",
                },
            },
            {
                "type": "file",
                "typeParams": { # 不同的类型所需要的参数不同，由typeParams来传递
                    "title": "CAE路22222径",
                    "objectName": "name",
                    "fileType": "cae3333",
                    "fileFilter": "CAE Files (*.cae);;All Files (*)"
                },
                "styleParams":{ # 控制样式的参数
                    "margin": [0, 0, 0, 0],
                    "space": 10,
                    "labWidth": 100,
                }
            },
            {
                "type": "file",
                "typeParams": { # 不同的类型所需要的参数不同，由typeParams来传递
                    "title": "CAE33333路径",
                    "objectName": "name",
                    "fileType": "cae2222",
                    "fileFilter": "CAE Files (*.cae);;All Files (*)"
                },
                "styleParams":{ # 控制样式的参数
                    "margin": [0, 0, 0, 0],
                    "space": 10,
                    "labWidth": 100,
                }
            },
            {},
            {
                "type": "tools",
                "typeParams": { # 不同的类型所需要的参数不同，由typeParams来传递
                    "items": [
                        {
                            "title": "确定",
                            "objectName": "OK",
                            "action": lambda: print("确定"),
                        },
                        {
                            "title": "取消",
                            "objectName": "export",
                            "action":lambda: dlg.reject(),
                        }
                    ],
                },
                "styleParams":{ # 控制样式的参数
                    "margin": [0, 0, 0, 0],
                    "space": 10,
                }
            },
        ]
    }
    ui = UiCustomDbPage(uiConfigData)
    ui._setup_ui(dlg)
    dlg.adjustSize()
    dlg.show()
    sys.exit(app.exec())